package chc

import (
	"errors"
	"time"

	"github.com/jmoiron/sqlx"
)

type ChSession struct {
	Connect     *sqlx.DB
	Config      *Config
	SingleConns []*sqlx.DB
}

var (
	chSession = &ChSession{}

	Debug            = true
	DefaultRowsLimit = -1
	DefaultTimeLoc   = time.Local
	ErrTxHasBegan    = errors.New("<Ormer.Begin> transaction already begin")
	ErrTxDone        = errors.New("<Ormer.Commit/Rollback> transaction not begin")
	ErrMultiRows     = errors.New("<QuerySeter> return multi rows")
	ErrNoRows        = errors.New("<QuerySeter> no row found")
	ErrStmtClosed    = errors.New("<QuerySeter> stmt already closed")
	ErrArgs          = errors.New("<Ormer> args error may be empty")
	ErrNotImplement  = errors.New("have not implement")
	ErrMissPK        = errors.New("missed pk value")
	errSkipField     = errors.New("skip field")
	ErrEmpty         = errors.New("var is nil")
)

func RegisterDataBase(config *Config) (err error) {
	chSession.Config = config

	if nil == config.DefaultTimeLoc {
		config.DefaultTimeLoc = time.Local
	}
	DefaultTimeLoc = config.DefaultTimeLoc

	return connection(config)
}

func RegisterModel(models ...interface{}) {
	for _, model := range models {
		registerModel("", model, true)
	}
}

func RegisterModelWithPrefix(prefixOrSuffix string, models ...interface{}) {
	for _, model := range models {
		registerModel(prefixOrSuffix, model, true)
	}
}

func RegisterModelWithSuffix(prefixOrSuffix string, models ...interface{}) {
	for _, model := range models {
		registerModel(prefixOrSuffix, model, false)
	}
}

func Insert(md interface{}) (err error) {
	return crudInsert(md)
}

func InsertMulti(mds interface{}) (err error) {
	return crudInsertMulti(mds)
}

func Delete(md interface{}, cols ...string) (int64, error) {
	return crudDelete(md, cols...)
}

func Update(md interface{}, cols ...string) (int64, error) {
	return crudUpdate(md, cols...)
}

func Read(md interface{}, cols ...string) error {
	return crudRead(md, cols...)
}

func ReadBatch(md interface{}, mds interface{}, cols ...string) (int64, error) {
	return crudReadBatch(md, mds, cols...)
}

func QueryTable(ptrStructOrTableName interface{}) (qs *QuerySet) {
	return queryTable(ptrStructOrTableName)
}

func Raw(query string, args ...interface{}) *RawSet {
	return newRawSet(query, args...)
}
